home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 16
/
Aminet 16 (1996)(GTI - Schatztruhe)[!][Dec 1996].iso
/
Aminet
/
comm
/
term
/
term_source.lha
/
Extras
/
Source
/
gtlayout-source.lha
/
LTP_LayoutGroup.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-10-03
|
20KB
|
825 lines
/*
** GadTools layout toolkit
**
** Copyright © 1993-1996 by Olaf `Olsen' Barthel
** Freely distributable.
**
** :ts=4
*/
#ifndef _GTLAYOUT_GLOBAL_H
#include "gtlayout_global.h"
#endif
#ifdef NOT_FUNCTIONAL
/* LTP_ShuffleGroup(LayoutHandle *Handle,ObjectNode *Group):
*
* Propagate size relationships between groups on the
* same tree level.
*
* On second thought, this was not such a good idea after
* all. I'll redo the stuff when I find the time.
*/
VOID
LTP_ShuffleGroup(LayoutHandle *Handle,ObjectNode *Group)
{
if(!Handle->Failed)
{
ObjectNode *Node;
LONG WidthCount = 0,
HeightCount = 0;
// First step: count the number of nodes which should share
// the sizes with other groups. Validate the
// group relationships on the fly, cancelling
// links which point to nonexistant objects.
SCANGROUP(Group,Node)
{
if(Node->Type == GROUP_KIND)
{
// Use the size of another group?
if(Node->Special.Group.UseWidth != -1)
{
ObjectNode *Other;
BOOL GotIt = FALSE;
// Scan the list for the group in question...
SCANGROUP(Group,Other)
{
// Is it this one?
if(Other != Node && Node->ID == Node->Special.Group.UseWidth)
{
GotIt = TRUE;
break;
}
}
// If this one is valid, update the counter,
// else cancel the link
if(GotIt)
WidthCount++;
else
Node->Special.Group.UseWidth = -1;
}
if(Node->Special.Group.UseHeight != -1)
{
ObjectNode *Other;
BOOL GotIt = FALSE;
SCANGROUP(Group,Other)
{
if(Other != Node && Node->ID == Node->Special.Group.UseHeight)
{
GotIt = TRUE;
break;
}
}
if(GotIt)
HeightCount++;
else
Node->Special.Group.UseHeight = -1;
}
}
}
// Second step: If any valid relationships were found,
// propagate the sizes.
if(WidthCount || HeightCount)
{
ObjectNode **Table;
LONG Total = sizeof(ObjectNode *) * MAX(WidthCount,HeightCount);
// Some temporary storage for keeping the nodes
if(Table = (ObjectNode **)LTP_Alloc(Handle,Total))
{
LONG Handled = 0,Collected = 0,Wanted = -1,i,MaxWidth,MaxHeight;
// Loop until all width relationships are resolved.
while(Handled < WidthCount)
{
Node = (ObjectNode *)Group->Special.Group.ObjectList.mlh_Head;
// Scan until we hit the end
while(Node->Node.mln_Succ)
{
// Is this a group we didn't check yet, but would
// need to take a look at?
if(Node->Type == GROUP_KIND && Node->Special.Group.UseWidth != -1 && !(Node->Special.Group.MiscFlags & GROUPF_WidthDone))
{
// Should we keep this one?
if(Wanted == -1 || Node->ID == Wanted)
{
// Keep this one
Table[Collected++] = Node;
// Don't check this one again
Node->Special.Group.MiscFlags |= GROUPF_WidthDone;
// We'll search for this one unless
// it points nowhere
if((Wanted = Node->Special.Group.UseWidth) == -1)
break;
else // Start again...
Node = (ObjectNode *)Group->Special.Group.ObjectList.mlh_Head;
}
else
Node = (ObjectNode *)Node->Node.mln_Succ;
}
else
Node = (ObjectNode *)Node->Node.mln_Succ;
}
// Determine maximum width of objects
for(i = MaxWidth = 0 ; i < Collected ; i++)
{
if(Table[i]->Width > MaxWidth)
MaxWidth = Table[i]->Width;
}
// Make all objects as large as the largest object
for(i = 0 ; i < Collected ; i++)
Table[i]->Width = MaxWidth;
// Update the counter
Handled += Collected;
// Scan until all references are resolved
Collected = 0;
}
Handled = 0;
while(Handled < HeightCount)
{
Node = (ObjectNode *)Group->Special.Group.ObjectList.mlh_Head;
while(Node->Node.mln_Succ)
{
if(Node->Type == GROUP_KIND && Node->Special.Group.UseHeight != -1 && !(Node->Special.Group.MiscFlags & GROUPF_HeightDone))
{
if(Wanted == -1 || Node->ID == Wanted)
{
Table[Collected++] = Node;
Node->Special.Group.MiscFlags |= GROUPF_HeightDone;
if((Wanted = Node->Special.Group.UseHeight) == -1)
break;
else
Node = (ObjectNode *)Group->Special.Group.ObjectList.mlh_Head;
}
else
Node = (ObjectNode *)Node->Node.mln_Succ;
}
else
Node = (ObjectNode *)Node->Node.mln_Succ;
}
for(i = MaxHeight = 0 ; i < Collected ; i++)
{
if(Table[i]->Height > MaxHeight)
MaxHeight = Table[i]->Height;
}
for(i = 0 ; i < Collected ; i++)
Table[i]->Height = MaxHeight;
Handled += Collected;
Collected = 0;
}
LTP_Free(Handle,Table,Total);
}
}
// Step three: do the just the same to all the other groups
// (tail recursion).
SCANGROUP(Group,Node)
{
if(Node->Type == GROUP_KIND)
LTP_ShuffleGroup(Handle,Node);
}
}
}
#endif // NOT_FUNCTIONAL
VOID
LTP_LayoutGroup(LayoutHandle *Handle,ObjectNode *Group)
{
if(!Handle->Failed)
{
ObjectNode *Node;
ObjectNode *ReturnKey;
ObjectNode *EscKey;
ObjectNode *CursorKey;
ObjectNode *TabKey;
ObjectNode *ActiveString;
LONG Left;
LONG Top;
LONG Width;
LONG Height;
LONG MaxWidth;
LONG MaxHeight;
BOOL DefaultCorrection;
Left = 0;
Top = 0;
ReturnKey = NULL;
EscKey = NULL;
CursorKey = NULL;
TabKey = NULL;
ActiveString = NULL;
DefaultCorrection = FALSE;
MaxWidth = 0;
MaxHeight = 0;
SCANGROUP(Group,Node)
{
LTP_DetermineSize(Handle,Node);
switch(Node->Type)
{
case BUTTON_KIND:
if(Node->Special.Button.ReturnKey)
ReturnKey = Node;
else
{
if(Node->Special.Button.EscKey)
EscKey = Node;
}
DefaultCorrection |= Node->Special.Button.DefaultCorrection;
break;
case CYCLE_KIND:
if(Node->Special.Cycle.TabKey)
TabKey = Node;
break;
#if defined(DO_POPUP_KIND) && defined(DO_BOOPSI_KIND)
case POPUP_KIND:
if(Node->Special.Popup.TabKey)
TabKey = Node;
break;
#endif
#if defined(DO_TAB_KIND) && defined(DO_BOOPSI_KIND)
case TAB_KIND:
if(Node->Special.Tab.TabKey)
TabKey = Node;
break;
#endif
case MX_KIND:
if(Node->Special.Radio.TabKey)
TabKey = Node;
break;
case PASSWORD_KIND:
case STRING_KIND:
if(Node->Special.String.Activate)
ActiveString = Node;
break;
case INTEGER_KIND:
if(Node->Special.Integer.Activate)
ActiveString = Node;
break;
case LISTVIEW_KIND:
if(Node->Special.List.CursorKey)
CursorKey = Node;
break;
}
if(Node->Width > MaxWidth)
MaxWidth = Node->Width;
if(Node->Height > MaxHeight)
MaxHeight = Node->Height;
}
if(ReturnKey || DefaultCorrection)
{
SCANGROUP(Group,Node)
{
#ifdef OLD_STYLE_DEFAULT_KEY
Node->GroupIndent = TRUE;
Node->Width += 4 + 4;
Node->Height += 2 + 2;
#else
Node->Width += 1 + 1;
Node->Height += 1 + 1;
#endif
if(Node->Width > MaxWidth)
MaxWidth = Node->Width;
if(Node->Height > MaxHeight)
MaxHeight = Node->Height;
}
}
if(Group->Special.Group.SameSize)
{
SCANGROUP(Group,Node)
{
if(Node->Width < MaxWidth && Node->Type != YBAR_KIND && Node->Type != CHECKBOX_KIND)
{
if(Node->Type == GROUP_KIND && !Node->Special.Group.NoIndent)
Node->Special.Group.ExtraLeft += (MaxWidth - Node->Width) / 2;
Node->Width = MaxWidth;
}
if(Node->Height < MaxHeight && Node->Type != XBAR_KIND && Node->Type != CHECKBOX_KIND)
{
if(Node->Type == GROUP_KIND && !Node->Special.Group.NoIndent)
Node->Special.Group.ExtraTop += (MaxHeight - Node->Height) / 2;
Node->Height = MaxHeight;
}
}
}
if(Group->Special.Group.Horizontal)
{
LONG x,y,w,MaxTop = 0,MaxWidth = 0,MaxHeight = 0,Count = 0;
if(Group->Node.mln_Pred->mln_Pred && Group->Special.Group.LastAttributes)
{
ObjectNode *LastGroup = (ObjectNode *)Group->Node.mln_Pred;
MaxTop = LastGroup->Special.Group.MaxOffset;
MaxHeight = LastGroup->Special.Group.MaxSize;
}
SCANGROUP(Group,Node)
{
if(!LIKE_STRING_KIND(Node) || Node->Special.String.LinkID == -1)
{
if(!Group->Special.Group.Paging && Count++)
{
if(Node->ExtraSpace > 0)
x = Left + Node->ExtraSpace * Handle->InterWidth;
else
{
if(Node->ExtraSpace < 0)
x = Left - Node->ExtraSpace;
else
x = Left + Handle->InterWidth;
}
}
else
x = Left;
y = Top;
w = Node->Width;
switch(Node->LabelPlace)
{
case PLACE_LEFT:
if(Node->Type == MX_KIND)
{
x += Node->Special.Radio.LabelWidth + INTERWIDTH;
if(Node->Label)
{
if(Node->Special.Radio.TitlePlace == PLACETEXT_LEFT)
x += Node->LabelWidth + INTERWIDTH;
else
w += INTERWIDTH + Node->LabelWidth;
}
}
else
{
if(Node->Label || (Node->Type == BOX_KIND && Node->Special.Box.Labels))
x += Node->LabelWidth + INTERWIDTH;
}
break;
case PLACE_RIGHT:
if(Node->Type == MX_KIND)
{
w += INTERWIDTH + Node->Special.Radio.LabelWidth;
if(Node->Label)
{
if(Node->Special.Radio.TitlePlace == PLACETEXT_LEFT)
x += Node->LabelWidth + INTERWIDTH;
else
w += INTERWIDTH + Node->LabelWidth;
}
}
else
{
if(Node->Label || (Node->Type == BOX_KIND && Node->Special.Box.Labels))
w += INTERWIDTH + Node->LabelWidth;
}
break;
case PLACE_ABOVE:
if(Node->Label || (Node->Type == BOX_KIND && Node->Special.Box.Labels))
{
if(Node->Type == LISTVIEW_KIND && Node->Special.List.TextAttr && Node->Special.List.FlushLabelLeft)
y += Node->Special.List.FixedGlyphHeight + INTERHEIGHT;
else
y += Handle->GlyphHeight + INTERHEIGHT;
}
break;
}
if(Node->Type == SLIDER_KIND)
{
if(Node->Special.Slider.LevelPlace == PLACETEXT_RIGHT && Node->Special.Slider.LevelFormat)
w += INTERWIDTH + Node->Special.Slider.LevelWidth;
if(Node->Special.Slider.LevelPlace == PLACETEXT_LEFT && Node->LabelPlace != PLACE_LEFT && Node->Special.Slider.LevelFormat)
x += INTERWIDTH + Node->Special.Slider.LevelWidth;
}
#ifdef DO_LEVEL_KIND
if(Node->Type == LEVEL_KIND)
{
if(Node->Special.Level.LevelPlace == PLACETEXT_RIGHT)
w += INTERWIDTH + Node->Special.Level.MaxLevelWidth;
if(Node->Special.Level.LevelPlace == PLACETEXT_LEFT && Node->LabelPlace != PLACE_LEFT)
x += INTERWIDTH + Node->Special.Level.MaxLevelWidth;
}
#endif /* DO_LEVEL_KIND */
if(Node->Type == LISTVIEW_KIND && Node->Special.List.ExtraLabelWidth)
x += Node->Special.List.ExtraLabelWidth + INTERWIDTH;
if(y > MaxTop)
MaxTop = y;
if(Node->Height > MaxHeight)
MaxHeight = Node->Height;
if(Node->LabelPlace == PLACE_BELOW && Node->Label)
{
LONG Height;
if(Node->Type == LISTVIEW_KIND && Node->Special.List.TextAttr && Node->Special.List.FlushLabelLeft)
Height = Node->Height + INTERHEIGHT + Node->Special.List.FixedGlyphHeight;
else
Height = Node->Height + INTERHEIGHT + Handle->GlyphHeight;
if(Height > MaxHeight)
MaxHeight = Height;
}
else
{
if(Node->Height > MaxHeight)
MaxHeight = Node->Height;
}
if(x + w > MaxWidth)
MaxWidth = x+w;
Node->Left = x;
if(!Group->Special.Group.Paging)
Left = x + w;
}
}
SCANGROUP(Group,Node)
{
if(!LIKE_STRING_KIND(Node) || Node->Special.String.LinkID == -1)
{
Node->Top = MaxTop;
if(Node->Height < MaxHeight)
{
#ifdef DO_BOOPSI_KIND
if((Node->Type == PALETTE_KIND && !Node->Special.Palette.UsePicker) || Node->Type == LISTVIEW_KIND || (Node->Type == BOOPSI_KIND && !Node->Special.BOOPSI.ExactHeight))
#else
if((Node->Type == PALETTE_KIND && !Node->Special.Palette.UsePicker) || Node->Type == LISTVIEW_KIND || Node->Type == BOOPSI_KIND)
#endif /* DO_BOOPSI_KIND */
Node->Height = MaxHeight;
else
{
if(Node->Type == GROUP_KIND)
{
if(Node->Special.Group.Spread)
LTP_Spread(Handle,Node,Node->Width,MaxHeight);
else
{
if(!Node->Special.Group.NoIndent)
Node->Special.Group.ExtraTop += (MaxHeight - Node->Height) / 2; /* !FIX! */
}
Node->Height = MaxHeight;
}
}
}
}
}
Group->Special.Group.MaxOffset = MaxTop;
Group->Special.Group.MaxSize = MaxHeight;
if(Group->Special.Group.Paging)
Width = MaxWidth;
else
Width = Left;
Height = MaxTop + MaxHeight;
}
else
{
LONG x,y,w,MaxLeft = 0,MaxWidth = 0,MaxHeight = 0,Count = 0;
if(Group->Node.mln_Pred->mln_Pred && Group->Special.Group.LastAttributes)
{
ObjectNode *LastGroup = (ObjectNode *)Group->Node.mln_Pred;
MaxLeft = LastGroup->Special.Group.MaxOffset;
MaxWidth = LastGroup->Special.Group.MaxSize;
}
SCANGROUP(Group,Node)
{
if(!LIKE_STRING_KIND(Node) || Node->Special.String.LinkID == -1)
{
if(!Group->Special.Group.Paging && Count++)
{
if(Node->ExtraSpace > 0)
y = Top + Node->ExtraSpace * Handle->InterHeight;
else
{
if(Node->ExtraSpace < 0)
y = Top - Node->ExtraSpace;
else
y = Top + Handle->InterHeight;
}
}
else
y = Top;
w = Node->Width;
x = Left;
switch(Node->LabelPlace)
{
case PLACE_LEFT:
if(Node->Type == MX_KIND)
{
x += Node->Special.Radio.LabelWidth + INTERWIDTH;
if(Node->Label)
{
if(Node->Special.Radio.TitlePlace == PLACETEXT_LEFT)
x += Node->LabelWidth + INTERWIDTH;
}
}
else
{
if(Node->Label || (Node->Type == BOX_KIND && Node->Special.Box.Labels))
x += Node->LabelWidth + INTERWIDTH;
}
break;
case PLACE_RIGHT:
if(Node->Type == MX_KIND)
{
w += INTERWIDTH + Node->Special.Radio.LabelWidth;
if(Node->Label)
{
if(Node->Special.Radio.TitlePlace == PLACETEXT_LEFT)
x += Node->LabelWidth + INTERWIDTH;
else
w += INTERWIDTH + Node->LabelWidth;
}
}
else
{
if(Node->Label || (Node->Type == BOX_KIND && Node->Special.Box.Labels))
w += INTERWIDTH + Node->LabelWidth;
}
break;
case PLACE_ABOVE:
if(Node->Label || (Node->Type == BOX_KIND && Node->Special.Box.Labels))
{
if(Node->Type == LISTVIEW_KIND && Node->Special.List.TextAttr && Node->Special.List.FlushLabelLeft)
y += Node->Special.List.FixedGlyphHeight + INTERHEIGHT;
else
y += Handle->GlyphHeight + INTERHEIGHT;
}
break;
}
if(Node->Type == SLIDER_KIND)
{
if(Node->Special.Slider.LevelPlace == PLACETEXT_RIGHT && Node->Special.Slider.LevelFormat)
w += INTERWIDTH + Node->Special.Slider.LevelWidth;
if(Node->Special.Slider.LevelPlace == PLACETEXT_LEFT && Node->LabelPlace != PLACE_LEFT && Node->Special.Slider.LevelFormat)
x += INTERWIDTH + Node->Special.Slider.LevelWidth;
}
#ifdef DO_LEVEL_KIND
if(Node->Type == LEVEL_KIND)
{
if(Node->Special.Level.LevelPlace == PLACETEXT_RIGHT)
w += INTERWIDTH + Node->Special.Level.MaxLevelWidth;
if(Node->Special.Level.LevelPlace == PLACETEXT_LEFT && Node->LabelPlace != PLACE_LEFT)
x += INTERWIDTH + Node->Special.Level.MaxLevelWidth;
}
#endif /* DO_LEVEL_KIND */
if(Node->Type == LISTVIEW_KIND && Node->Special.List.ExtraLabelWidth)
x += Node->Special.List.ExtraLabelWidth + INTERWIDTH;
if(x > MaxLeft)
MaxLeft = x;
if(w > MaxWidth)
MaxWidth = w;
if(y + Node->Height > MaxHeight)
MaxHeight = y + Node->Height;
Node->Top = y;
if(!Group->Special.Group.Paging)
Top = y + Node->Height;
if(Node->LabelPlace == PLACE_BELOW && Node->Label)
{
if(Node->Type == LISTVIEW_KIND && Node->Special.List.TextAttr && Node->Special.List.FlushLabelLeft)
Top += INTERHEIGHT + Node->Special.List.FixedGlyphHeight;
else
Top += INTERHEIGHT + Handle->GlyphHeight;
}
}
}
SCANGROUP(Group,Node)
{
if(!LIKE_STRING_KIND(Node) || Node->Special.String.LinkID == -1)
{
Node->Left = MaxLeft;
if(Node->Type == GROUP_KIND && Group->Special.Group.Paging && !Node->Special.Group.NoIndent)
Node->Special.Group.ExtraTop += (MaxHeight - Node->Height) / 2;
if(Node->Width < MaxWidth)
{
if(Node->Type == GROUP_KIND)
{
if(Node->Special.Group.Spread)
LTP_Spread(Handle,Node,MaxWidth,Node->Height);
else
{
if(!Node->Special.Group.NoIndent)
Node->Special.Group.ExtraLeft += (MaxWidth - Node->Width) / 2;
}
Node->Width = MaxWidth;
}
else
{
#ifdef DO_BOOPSI_KIND
if((Node->Type == PALETTE_KIND && !Node->Special.Palette.UsePicker) || (Node->Type == LISTVIEW_KIND && !Node->Special.List.LockSize) || (Node->Type == TEXT_KIND && !Node->Special.Text.LockSize) || Node->Type == GAUGE_KIND || Node->Type == NUMBER_KIND || Node->Type == CYCLE_KIND || LIKE_STRING_KIND(Node) || Node->Type == INTEGER_KIND || Node->Type == BUTTON_KIND || Node->Type == BOX_KIND || Node->Type == SCROLLER_KIND || Node->Type == SLIDER_KIND || Node->Type == LEVEL_KIND || (Node->Type == BOOPSI_KIND && !Node->Special.BOOPSI.ExactWidth) || Node->Type == POPUP_KIND || Node->Type == TAB_KIND || Node->Type == BLANK_KIND)
#else
if((Node->Type == PALETTE_KIND && !Node->Special.Palette.UsePicker) || (Node->Type == LISTVIEW_KIND && !Node->Special.List.LockSize) || (Node->Type == TEXT_KIND && !Node->Special.Text.LockSize) || Node->Type == GAUGE_KIND || Node->Type == NUMBER_KIND || Node->Type == CYCLE_KIND || LIKE_STRING_KIND(Node) || Node->Type == INTEGER_KIND || Node->Type == BUTTON_KIND || Node->Type == BOX_KIND || Node->Type == SCROLLER_KIND || Node->Type == SLIDER_KIND || Node->Type == LEVEL_KIND || Node->Type == BLANK_KIND)
#endif /* DO_BOOPSI_KIND */
{
if(Node->Label && Node->LabelPlace == PLACE_RIGHT)
Node->Width = MaxWidth - (INTERWIDTH + Node->LabelWidth);
else
Node->Width = MaxWidth;
}
}
}
}
}
Group->Special.Group.MaxOffset = MaxLeft;
Group->Special.Group.MaxSize = MaxWidth;
if(Group->Special.Group.Paging)
Height = MaxHeight;
else
Height = Top;
Width = MaxLeft + MaxWidth;
}
Group->Left = 0;
Group->Top = 0;
Group->Width = Width;
Group->Height = Height;
if(Group->Label || Group->Special.Group.Frame)
{
if(Group->Label)
{
Group->LabelWidth = LT_LabelWidth(Handle,Group->Label) + 2 * Handle->GlyphWidth;
Group->Height += Handle->GlyphHeight + 2 * Handle->InterHeight + 3;
}
else
{
Group->LabelWidth = 0;
Group->Height += 2 + 2 * Handle->InterHeight + 3;
}
if(Group->LabelWidth > Group->Width)
{
if(!Node->Special.Group.NoIndent)
Group->Special.Group.ExtraLeft += (Group->LabelWidth - Group->Width) / 2;
Group->Width = Group->LabelWidth;
}
Group->Width += 2 * (Handle->GlyphWidth + Handle->InterWidth) + 8;
}
if(Group->Special.Group.IndentX)
{
Group->Width += 2 * Handle->InterWidth;
Group->Special.Group.ExtraLeft += Handle->InterWidth;
}
if(Group->Special.Group.IndentY)
{
Group->Height += 2 * Handle->InterHeight;
Group->Special.Group.ExtraTop += Handle->InterHeight;
}
if(ReturnKey)
Handle->ReturnKey = ReturnKey;
if(EscKey)
Handle->EscKey = EscKey;
if(CursorKey)
Handle->CursorKey = CursorKey;
if(TabKey)
Handle->TabKey = TabKey;
if(ActiveString)
Handle->ActiveString = ActiveString;
}
}